package com.uyaer.wheel.game
{
	import com.uyaer.wheel.Player;
	import com.uyaer.wheel.common.Common;
	import com.uyaer.wheel.common.Config;
	import com.uyaer.wheel.common.Dir;
	import com.uyaer.wheel.common.UserData;
	import com.uyaer.wheel.events.EventType;
	import com.uyaer.wheel.game.map.MapCellType;
	import com.uyaer.wheel.game.map.RandomMap;
	import com.uyaer.wheel.menu.MenuType;
	import com.uyaer.wheel.nape.BodyPool;
	import com.uyaer.wheel.plus.AD;
	import com.uyaer.wheel.plus.Audio;
	import com.uyaer.wheel.plus.Keybord;
	import com.uyaer.wheel.plus.Sensor;
	import com.uyaer.wheel.res.ResManager;
	
	import flash.events.KeyboardEvent;
	import flash.geom.Point;
	import flash.ui.Keyboard;
	import flash.ui.Multitouch;
	
	import nape.callbacks.CbEvent;
	import nape.callbacks.InteractionCallback;
	import nape.callbacks.InteractionListener;
	import nape.callbacks.InteractionType;
	import nape.geom.Vec2;
	import nape.phys.Body;
	import nape.space.Space;
	
	import starling.display.DisplayObject;
	import starling.display.Image;
	import starling.display.Quad;
	import starling.display.Sprite;
	import starling.events.Event;
	import starling.events.Touch;
	import starling.events.TouchEvent;
	import starling.events.TouchPhase;
	
	public class Game extends Sprite
	{
		public static const RUNNING:String = "running";
		public static const PAUSE:String = "pause";
		
		private var level_max:int = 30; //最高等级
		private var level_distance:Array = new Array(); //升级经验
		private var level_speed:Array = new Array(); //升级后速度加成
		private var level_map_speed:Array = new Array(); //升级后地图速度加成
		private var space:Space;
		private var player:Player;
		private var startMask:Quad;
		private var startLabel:Image;
		private var _state:String;
		private var im:Vec2 = new Vec2(); 
		private var maxSpeed:Number;
		public function Game()
		{
			if(stage){
				onAdded();
			}else{
				this.addEventListener(Event.ADDED_TO_STAGE,onAdded);
			}
		}
		
		private function onAdded(e:Event = null):void{
			this.removeEventListener(Event.ADDED_TO_STAGE,onAdded);
			
			state = RUNNING;
			
			var prev:Number = 1.1;
			for(var i:int = 1; i <= level_max; i ++){
				level_distance.push(5*i*(i+1));
				if(i == 1){
					level_speed.push(1.1);
					level_map_speed.push(1.1);
				}else{ 
					prev *= 1.1;
					level_speed.push(prev);
					level_map_speed.push(prev);
				}
			}
			
			space = new Space(new Vec2(0,0));
			var listener:InteractionListener = new InteractionListener(
				CbEvent.ONGOING,InteractionType.SENSOR,Common.awardCbType,Common.meCbType,collisionHandler);
			space.listeners.add(listener);
			Common.space = space;
			
			player = new Player();
			player.x = Common.W>>1;
			player.y = Common.H>>1;
			addChild(player);
			
			Background.instance.start(stage);
			RandomMap.instance.start(this);
			
			startMask = new Quad(Common.W,Common.H,0x0);
			startMask.alpha = 0.35
			addChild(startMask);
			startLabel = new Image(ResManager.me.getTexture("menu_clickgame"));
			startLabel.touchable = false;
			startLabel.x = Common.W>>1;
			startLabel.pivotX = startLabel.width>>1;
			startLabel.y = Common.H*0.52;
			startLabel.scaleX = startLabel.scaleY = Common.S;
			addChild(startLabel);
			
			stage.addEventListener(EventType.RUN_GAME,onRunGame);
			
			Audio.me.playGaming();
			AD.me.showGameAD();
			Common.stage.addEventListener("deactivate",onDeactivate);
			Common.stage.addEventListener("activate",onActivate);
		}
		
		private function onRunGame():void{
			stage.removeEventListener(EventType.RUN_GAME,onRunGame);
			
			startMask.addEventListener(TouchEvent.TOUCH,onTouch);
		}
		
		private function onTouch(e:TouchEvent):void{
			var touch:Touch = e.getTouch(this);
			if(touch && touch.phase == TouchPhase.ENDED && e.target == startMask){
				initPlugs();
				stage.addEventListener(Event.ENTER_FRAME,onEnterFrame);	
				startMask.removeFromParent();
				startLabel.removeFromParent();
				Common.stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyHandler,false,0,true);
			}
		}
		
		private function initPlugs():void{
			if(Sensor.support){
				Sensor.instance.start();
			}else if(Multitouch.supportsTouchEvents){
				
			}
			Keybord.instance.start(Common.stage);
		}
		
		private function collisionHandler(e:InteractionCallback):void{
			var awardBody:Body = e.int1.cbTypes.has(Common.awardCbType)?e.int1.castBody:e.int2.castBody;
			var star:Image = awardBody.userData.data.texture as Image;
			if(star){
				if(awardBody.userData.data.textureType == MapCellType.STAR){
					var pos:Point = star.localToGlobal(new Point());
					stage.dispatchEventWith(EventType.EAT_STAR,false,pos);
				}else if(awardBody.userData.data.textureType == MapCellType.POP){
					stage.dispatchEventWith(EventType.EAT_POP);
				}
			}
			space.bodies.remove(awardBody);
			BodyPool.recycleBox(awardBody);
		}
		
		private function onEnterFrame(e:Event):void{
			space.step(1/30);
			var body:Body;
			var data:Object;
			var texture:DisplayObject;
			for (var i:int = space.bodies.length - 1; i >= 0; i--){
				body = space.bodies.at(i);
				data = body.userData.data;
				texture = data.texture;
				if(data.removeIndex == RandomMap.instance.removeIndex){
					space.bodies.remove(body);
					BodyPool.recycleBox(body);
				}else{
					if(texture){
						texture.x = body.bounds.x;
						texture.y = body.bounds.y+body.bounds.height;
					}
				}
			}
			
			body = player.body;
			player.rotation = body.rotation;
			player.x = body.position.x;
			player.y = body.position.y;
			if(player.state == Player.START_POP){
				player.body.velocity.setxy(0,0);
			}else if(player.state == Player.POPING){
				player.body.velocity.setxy(1500*Dir.dirX,1500*Dir.dirY);
			}else if(player.state == Player.NORMAL){
				im.setxy(55*Dir.dirX,55*Dir.dirY);
				im.mul(level_speed[UserData.me.level-1]);
				player.body.applyImpulse(im);
				if(player.state == Player.POPING){
					maxSpeed = 50;
				}else{
					maxSpeed = 350;
				}
				if(player.body.velocity.y < -maxSpeed)player.body.velocity.y = -maxSpeed;
				if(player.body.velocity.y > maxSpeed)player.body.velocity.y = maxSpeed;
				if(player.body.velocity.x < -maxSpeed)player.body.velocity.x = -maxSpeed;
				if(player.body.velocity.x > maxSpeed)player.body.velocity.x = maxSpeed;
			}
			if(player.state == Player.START_POP || player.state == Player.END_POP){
				return;
			}
			player.updateDy();
			var p:Point = player.localToGlobal(new Point());
			if(Config.isUp){
				if(p.y<0){
					player.body.velocity.y = 0;
				}else if(p.y>=Common.H){ //gameover
					this.pause();
					stage.dispatchEventWith(EventType.MENU_SELECT,false,MenuType.DIE_GAME);
					return;
				}
				// 提升等级规则
				this.checkUpLevel();
				//地图移动
				if(p.y<=Common.H/12){
					RandomMap.instance.move(8*level_map_speed[UserData.me.level-1]);
				}else if(p.y<=Common.H/6){
					RandomMap.instance.move(4*level_map_speed[UserData.me.level-1]);
				}else if(p.y<=Common.H/3){
					RandomMap.instance.move(2*level_map_speed[UserData.me.level-1]);
				}else{
					RandomMap.instance.move(1*level_map_speed[UserData.me.level-1]);
				}
			}else{
				if(p.y<0){
					this.pause();
					stage.dispatchEventWith(EventType.MENU_SELECT,false,MenuType.DIE_GAME);
					return;
				}else if(p.y>=Common.H){ //gameover
					player.body.velocity.y = 0;
				}
				// 提升等级规则
				this.checkUpLevel();
				//地图移动
				if(p.y>=Common.H-Common.H/12){
					RandomMap.instance.move(8*level_map_speed[UserData.me.level-1]);
				}else if(p.y>=Common.H-Common.H/6){
					RandomMap.instance.move(4*level_map_speed[UserData.me.level-1]);
				}else if(p.y>=Common.H-Common.H/3){
					RandomMap.instance.move(2*level_map_speed[UserData.me.level-1]);
				}else{
					RandomMap.instance.move(1*level_map_speed[UserData.me.level-1]);
				}
			}
		}
		
		private function checkUpLevel():void{
			if(UserData.me.level == level_max){ //最大等级不检查了
				return;
			}
			if(RandomMap.instance.removeIndex>=level_distance[UserData.me.level-1]){
				//升级成功
				if(Config.debug){trace("level up!!");}
				UserData.me.level++;
				stage.dispatchEventWith(EventType.LEVEL_UP);
			}
		}
		
		private function onKeyHandler(e:KeyboardEvent):void{
			if(e.type == KeyboardEvent.KEY_DOWN){
				if(e.keyCode == Keyboard.BACK){
					e.preventDefault();
					e.stopPropagation();
					if(state == RUNNING){
						this.pause();
						stage.dispatchEventWith(EventType.MENU_SELECT,false,MenuType.PAUSE_GAME);
					}
				}
			}
		}
		
		private function onDeactivate(e:*):void{
			Audio.me.stopGaming();	
		}
		private function onActivate(e:*):void{
			Audio.me.playGaming();	
		}
		
		/**
		 *暂停游戏 
		 */		
		public function pause():void{
			state = PAUSE;
			startMask.touchable = false;
			stage.removeEventListener(Event.ENTER_FRAME,onEnterFrame);	
			stage.addEventListener(EventType.GAME_RESUME,resume);
		}
		
		/**
		 *恢复暂停 
		 */		
		public function resume():void{
			state = RUNNING;
			startMask.touchable = true;
			stage.addEventListener(Event.ENTER_FRAME,onEnterFrame);	
			stage.removeEventListener(EventType.GAME_RESUME,resume);
		}
		
		/**
		 *销毁游戏 
		 * 
		 */		
		public function destory(dispose:Boolean = true):void{
			Common.stage.removeEventListener(KeyboardEvent.KEY_DOWN,onKeyHandler);
			stage.removeEventListener(Event.ENTER_FRAME,onEnterFrame);	
			stage.removeEventListener(EventType.GAME_RESUME,resume);
			Common.stage.removeEventListener("deactivate",onDeactivate);
			Common.stage.removeEventListener("activate",onActivate);
			
			Audio.me.stopGaming();
			AD.me.hideAD();
			
			Background.instance.destory();
			RandomMap.instance.stop();
			player.destory();
			var body:Body;
			for (var i:int = space.bodies.length-1; i>=0; i--){
				body = space.bodies.at(i);
				space.bodies.remove(body);
				BodyPool.recycleBox(body);
			}
			space.listeners.clear();
			space.bodies.clear();
			space.clear();
			space = null;
			this.dispose();
		}
		
		private function get state():String{
			return _state;
		}
		
		private function set state(value:String):void{
			_state = value;
			stage.dispatchEventWith(EventType.GAME_STATE_CHANGE,false,value);
		}
		
	}
}